<?php

namespace App\Http\Controllers;

use App\Exceptions\ApiException;
use App\Exceptions\ErrorCode;
use App\Models\User;
use App\Requests\AuthRequest;
use App\Resources\UserProfileResource;
use App\Services\AliyunOssService;
use App\Services\AuthService;
use App\Services\SocialAccountService;
use App\Services\UserService;
use App\Services\YouzanService;

class AuthController extends Controller
{
    protected $aliyunService;
    protected $authService;
    protected $socialAccountService;
    protected $userService;
    protected $youzanService;

    public function __construct(
        AliyunOssService $aliyunService,
        AuthService $authService,
        SocialAccountService $socialAccountService,
        UserService $userService,
        YouzanService $youzanService
    )
    {
        $this->aliyunService = $aliyunService;
        $this->authService = $authService;
        $this->socialAccountService = $socialAccountService;
        $this->userService = $userService;
        $this->youzanService = $youzanService;
    }

    /**
     * 用户在使用微信登录后需要与手机绑定的请求。
     * @param AuthRequest $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function changePhoneBinding(AuthRequest $request)
    {
        $openid = $request->get('openid');
        $phone = $request->get('phone');
        $area_code = $request->get('area_code');
        $auth_code = $request->get('auth_code');
        $user = $this->authService->changePhoneBinding($openid, $phone, $area_code, $auth_code);
        $youzan_login_data = $this->youzanService->login($user->id, $user->username, $user->avatar);
        return response()->json([
            'access_token' => auth()->tokenById($user->id),
            'token_type' => 'bearer',
            'expires_in' => auth()->factory()->getTTL() * 60,
            'youzan' => $youzan_login_data
        ]);
    }

    /**
     * 用户在个人中心发起更改微信绑定的请求。
     * @param AuthRequest $request
     * @return UserProfileResource
     */
    public function changeWechatBinding(AuthRequest $request)
    {
        $code = $request->get('code');
        $user = auth()->user();
        $change_user = $this->authService->changeWechatBinding($user, $code);
        return new UserProfileResource($change_user);
    }

    public function checkAuthCode(AuthRequest $request)
    {
        $data = $request->validated();
        $flash = isset($data['flash']) && $data['flash'] == 1;
        $valid = $this->authService->checkAuthCode($data['phone'], $data['area_code'], $data['auth_code'], $flash);
        return $valid ? response_success() : response_with_code('Invalid auth code', ErrorCode::INVALID_AUTH_CODE);
    }

    public function checkVersion(AuthRequest $request)
    {
        $build = $request->get('build');
        $platform = $request->get('platform');
        return $this->authService->checkForUpdate($build, $platform);
    }

    public function getOssPostOptions()
    {
        return $this->aliyunService->getPostObjectOption();
    }

    /**
     * APP 用户登录。
     * @param AuthRequest $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function login(AuthRequest $request)
    {
        $data = $request->validated();
        // 通过参数区分是密码登录还是验证码登录。
        if (isset($data['auth_code'])) {
            $user = $this->authService->loginByAuthCode($data['phone'], $data['area_code'], $data['auth_code']);
        } else {
            $user = $this->authService->loginByPassword($data['phone'], $data['area_code'], $data['password']);
        }
        $youzan_login_data = $this->youzanService->login($user->id, $user->username, $user->avatar);
        return response()->json([
            'access_token' => auth()->tokenById($user->id),
            'token_type' => 'bearer',
            'expires_in' => auth()->factory()->getTTL() * 60,
            'youzan' => $youzan_login_data
        ]);
    }

    public function refresh()
    {
        return response_with_token(auth()->refresh(true, true));
    }

    public function resetPassword(AuthRequest $request)
    {
        $data = $request->validated();
        if (!$this->authService->checkAuthCode($data['phone'], $data['area_code'], $data['auth_code'])) {
            throw new ApiException('验证码无效！', ErrorCode::INVALID_AUTH_CODE);
        }
        $user = User::where(['phone' => $data['phone'], 'area_code' => $data['area_code']])->first();
        if (!$user) {
            throw new ApiException('此手机未注册！', ErrorCode::USER_NOT_FOUND);
        }
        $user->password = bcrypt($data['password']);
        $user->save();
        return response_success();
    }

    public function sendAuthCode(AuthRequest $request)
    {
        $phone = $request->get('phone');
        $area_code = $request->get('area_code');
        try {
            $this->authService->sendAuthCode($phone, $area_code);
        } catch (\Exception $e) {
            $error = $e->getExceptions()['yunpian']->raw;
            throw new ApiException($error['detail'], $error['code']);
        }
        return response_success();
    }

    /**
     * 解决微信登录绑定手机账号冲突的情况。
     * 保留登录的微信绑定账号，封禁手机绑定的账号，并更新微信绑定账号的手机信息。
     * @param AuthRequest $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function solvePhoneBindingConflict(AuthRequest $request)
    {
        $openid = $request->get('openid');
        $phone = $request->get('phone');
        $area_code = $request->get('area_code');
        $user = $this->authService->solvePhoneBindingConflict($openid, $phone, $area_code);
        $youzan_login_data = $this->youzanService->login($user->id, $user->username, $user->avatar);
        return response()->json([
            'access_token' => auth()->tokenById($user->id),
            'token_type' => 'bearer',
            'expires_in' => auth()->factory()->getTTL() * 60,
            'youzan' => $youzan_login_data
        ]);
    }

    /**
     * 解决个人中心改绑微信时的账号冲突情况。
     * @param AuthRequest $request
     * @return UserProfileResource
     */
    public function solveWechatBindingConflict(AuthRequest $request)
    {
        $user = auth()->user();
        $openid = $request->get('openid');
        $change_user = $this->authService->solveWechatBindingConflict($user, $openid);
        return new UserProfileResource($change_user);
    }

    /**
     * 处理微信登录请求。
     * @param AuthRequest $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function wechatAuthorize(AuthRequest $request)
    {
        $auth_code = $request->get('code');
        $user = $this->authService->wechatAuthorize($auth_code);
        $youzan_login_data = $this->youzanService->login($user->id, $user->username, $user->avatar);
        return response()->json([
            'access_token' => auth()->tokenById($user->id),
            'token_type' => 'bearer',
            'expires_in' => auth()->factory()->getTTL() * 60,
            'youzan' => $youzan_login_data
        ]);
    }

    /**
     * 有赞商城初始化 token 接口。
     * @return \Illuminate\Http\JsonResponse
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function youzanInitToken()
    {
        $response = $this->youzanService->initToken();
        return response()->json($response);
    }

    /**
     * 有赞商城登录。
     * @return \Illuminate\Http\JsonResponse
     */
    public function youzanLogin()
    {
        $user = auth()->user();
        $response = $this->youzanService->login($user->id, $user->username, $user->avatar);
        return response()->json($response);
    }
}